package test.service.analysis;

import org.apache.commons.math3.stat.StatUtils;
import org.apache.commons.math3.stat.descriptive.moment.Kurtosis;
import org.apache.commons.math3.stat.descriptive.moment.Skewness;
import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation;
import org.apache.commons.math3.stat.descriptive.rank.Median;

import cn.hutool.core.util.NumberUtil;

/**
 * @Description TODO(这里用一句话描述这个类的作用)
 *
 * @author liuqinghua
 * @date 2023-9-13
 */
public class MathTest2 {
    public static void main(String[] args) {
        double[] values = new double[] { 3.35, 6.54, 2.21, 5.522, 4.522, 5.64, 3.45, 2.522, 2.88 };
        double[] values2 = new double[] { 0.89, 1.51, 0.379, 0.41, 0.712, 0.48, 0.54, 0.56, 0.43 };

        // 偏度系数
        System.out.println("一组数据的偏度系数：" + new Skewness().evaluate(values));
        System.out.println("一组数据的偏度系数（自定义公式）：" + skewness(values));
        // 峰度系数
        System.out.println("一组数据的峰度系数：" + new Kurtosis().evaluate(values));
        System.out.println("一组数据的峰度系数（自定义公式）：" + kurtosis(values));
    }

    /**
     * 计算几何标准差
     * 
     * @param values 计算数据数组
     * @return 几何标准差
     */
    private static double geoStandardDeviation(double[] values) {
        double v = 0.0;
        double sqrValue = 0.0;
        double powValue = 0.0;
        if (values != null) {
            int length = values.length;
            for (double d : values) {
                sqrValue = sqrValue + Math.pow(Math.log10(d), 2);
                powValue = powValue + Math.log10(d);
            }
            v = Math.pow(10, Math.sqrt((sqrValue - Math.pow(powValue, 2) / (double) length) / (double) (length - 1)));
        }
        return v;
    }

    /**
     * 计算偏度系数
     * 
     * @param values 计算数据数组
     * @return 偏度系数
     */
    private static double skewness(double[] values) {
        double v = 0.0;
        if (values != null) {
            int length = values.length;
            // 算数平均值
            double mean = StatUtils.mean(values);
            // 算数标准差
            double evaluate = new StandardDeviation(false).evaluate(values);
            for (double d : values) {
                v += Math.pow(d - mean, 3) / Math.pow(evaluate, 3);
            }
            v = v / (double) (length);
        }
        return v;
    }

    /**
     * 计算峰度系数
     * 
     * @param values 计算数据数组
     * @return 峰度系数
     */
    private static double kurtosis(double[] values) {
        double v = 0.0;
        if (values != null) {
            int length = values.length;
            // 算数平均值
            double mean = StatUtils.mean(values);
            // 算数标准差
            double evaluate = new StandardDeviation(false).evaluate(values);
            for (double d : values) {
                v += Math.pow(d - mean, 4) / Math.pow(evaluate, 4);
            }
            v = v / (double) (length) - 3.0;
        }
        return v;
    }

    /**
     * 计算内罗梅指数/综合指数
     * 
     * @param values 计算数据数组
     * @return 内罗梅指数
     */
    private static double neromeIndex(final double[] values) {
        double v = 0.0;
        if (values != null) {
            // 算数平均值
            double mean = StatUtils.mean(values);
            // 最大值
            double max = StatUtils.max(values);
            // 计算内罗梅指数
            v = Math.sqrt(NumberUtil.div(NumberUtil.add(Math.pow(mean, 2), Math.pow(max, 2)), 2));
        }
        return Double.isNaN(v) ? 0.0 : v;
    }
}
